package study.eggs.utils;

import java.lang.reflect.Field;
import java.util.Objects;

public final class FieldUtils {

    private FieldUtils() {
    }

    /**
     * 获取对象所有 Field
     *
     * @param obj -对象
     * @return Field[]
     */
    public static Field[] getAllField(Object obj) {
        if (Objects.isNull(obj)) {
            return null;
        }
        Field[] fields = obj.getClass().getDeclaredFields();
        return fields;
    }

    /**
     * 获取对象指定 Field
     *
     * @param obj  -对象
     * @param name -属性名
     * @return Field
     */
    public static Field getField(Object obj, String name) {
        if (Objects.isNull(obj)) {
            return null;
        }
        Field field;
        try {
            field = obj.getClass().getDeclaredField(name);
        } catch (NoSuchFieldException ex) {
            throw new RuntimeException("get field error!", ex);
        }
        return field;
    }

    /**
     * 设置值
     *
     * @param obj   -对象
     * @param name  -属性名
     * @param value -属性值
     */
    public static void setValue(Object obj, String name, Object value) {
        Field field = getField(obj, name);
        setValue(obj, field, value);
    }

    /**
     * 设置值
     *
     * @param obj   -对象
     * @param field -属性
     * @param value -属性值
     */
    public static void setValue(Object obj, Field field, Object value) {
        try {
            field.setAccessible(true);
            field.set(obj, value);
        } catch (IllegalAccessException ex) {
            throw new RuntimeException("set value error!", ex);
        }
    }

    /**
     * 获取值
     *
     * @param obj  -对象
     * @param name -属性名
     * @return T
     */
    public static <T> T getValue(Object obj, String name) {
        Field field = getField(obj, name);
        T value = getValue(obj, field);
        return value;
    }

    /**
     * 获取值
     *
     * @param obj   -对象
     * @param field -属性
     * @return T
     */
    public static <T> T getValue(Object obj, Field field) {
        T value;
        try {
            field.setAccessible(true);
            value = (T) field.get(obj);
        } catch (IllegalAccessException ex) {
            throw new RuntimeException("get value error!", ex);
        }
        return value;
    }
}
